package com.gz.seckill.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gz.seckill.dao.UserDao;
import com.gz.seckill.exception.GlobalException;
import com.gz.seckill.pojo.User;
import com.gz.seckill.service.UserService;
import com.gz.seckill.util.CookieUtil;
import com.gz.seckill.util.MD5Util;
import com.gz.seckill.util.UUIDUtil;
import com.gz.seckill.util.ValidatorUtil;
import com.gz.seckill.vo.LoginVo;
import com.gz.seckill.vo.RespBean;
import com.gz.seckill.vo.RespBeanEnum;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService {

    @Resource
    private UserDao userDao;

    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public RespBean doLogin(LoginVo loginVo, HttpServletRequest request, HttpServletResponse response) {

        //接收到mobile和password
        String mobile = loginVo.getMobile();
        String password = loginVo.getPassword();

        //判断手机号和密码是否为空
//        if (StringUtils.isEmpty(mobile) || StringUtils.isEmpty(password)) {
//            return RespBean.error(RespBeanEnum.LOGIN_ERROR);
//        } //被注解@NotNull替代

        //校验手机号码是否合格
//        if(!ValidatorUtil.isMobile(mobile)){
//            return RespBean.error(RespBeanEnum.MOBILE_ERROR);
//        }  //被自定义注解@IsMobile替代

        //查询DB，看看用户是否存在
        User user = userDao.selectById(mobile);
        if(user == null){ //说明用户不存在
//            return RespBean.error(RespBeanEnum.LOGIN_ERROR);
            throw new GlobalException(RespBeanEnum.LOGIN_ERROR);
        }

        //用户存在，比对密码
        //注意这里从loginVo取出的密码是中间密码，从客户端经过一次加密加盐处理的密码
        if (!MD5Util.MidPassToDBPass(password,user.getSlat()).equals(user.getPassword())){
//            return RespBean.error(RespBeanEnum.LOGIN_ERROR);
            throw new GlobalException(RespBeanEnum.LOGIN_ERROR);
        }


        //给每个用户生成唯一ticket
        String ticket = UUIDUtil.getUUID();
        //将登录成功的用户保存到session (本质是个map)
//        request.getSession().setAttribute(ticket,user);//即 k-uuid ,v-用户信息

        //为了实现分布式session，把登录的用户存放到redis
        redisTemplate.opsForValue().set("user:"+ticket,user);

        //将ticket保存到cookie
        CookieUtil.setCookie(request,response,"userTicket",ticket);


        //用token方法
        //由于我找的jwt工具类里面，总有几个爆红，不知道什么原因，这里就没改了
        //用token也很简单，步骤和session差不多，少了一个cookie
        //就是用token工具类保存一个信息比如mobile，
        // 再根据header、claims(信息)、签名(一个算法)三层加密，生成一个token
        //但是token不要存隐私信息如密码
        //然后工具类里面还有一个checkToken验证token的
        //当登录账号和密码验证成功时，用这个生成token，然后存入redis(可以按<userId,token>来存)来进行分布式token
        //之后访问其他路径，如果需要验证登录就可以从redis中取出token验证了
        // 其实与cookie+session一样的，甚至更简单了，因为工具类帮忙把token加密了
        //就不需要在用cookie保存userTicket了

        //登录成功
        //这里我们需要返回userTicket
        return RespBean.success(ticket);
    }

    @Override
    public User getUserByCookie(String userTicket,
                                HttpServletRequest request,
                                HttpServletResponse response) {
        if (!StringUtils.hasText(userTicket)) {
            return null;
        }

        //根据userTicket获取user
        User user = (User)redisTemplate.opsForValue().get("user:" + userTicket);
        if (user != null) { //刷新cookie生命周期
            CookieUtil.setCookie(request,response,"userTicket",userTicket);
        }
        return user;
    }

    @Override
    public RespBean updatePassword(String userTicket,String password, HttpServletRequest request, HttpServletResponse response) {

        User user = getUserByCookie(userTicket,request, response);
        if (user == null) {
            throw new GlobalException(RespBeanEnum.MOBILE_NOT_EXIST);
        }

        user.setPassword(MD5Util.inputPassToDBPass(password,user.getSlat()));
        int i = userDao.updateById(user);
        if (i == 1) { //更新成功
           redisTemplate.delete("user:"+userTicket);
           return RespBean.success();
        }

        return RespBean.error(RespBeanEnum.PASSWORD_UPDATE_FAIL);
    }
}
